/*
 *  ME218_I2C_top.c
 *  ArduinoOnXcode
 *
 *  Created by Rick Miley on 3/17/11.
 *  Copyright 2011 __MyCompanyName__. All rights reserved.
 *
 */

// #include "ME218_I2C_top.h"

/*
 TwoWire.cpp - TWI/I2C library for Wiring & Arduino
 Copyright (c) 2006 Nicholas Zambetti.  All right reserved.
 
 This library is free software; you can redistribute it and/or
 modify it under the terms of the GNU Lesser General Public
 License as published by the Free Software Foundation; either
 version 2.1 of the License, or (at your option) any later version.
 
 This library is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 Lesser General Public License for more details.
 
 You should have received a copy of the GNU Lesser General Public
 License along with this library; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 */

#include <ME218_I2C.h>


void TWI_begin(uint8_t address)
{
	twi_setAddress(address);
	twi_attachSlaveTxEvent(TWI_onRequestService);
	twi_attachSlaveRxEvent(TWI_onReceiveService);
	
	
	TWI_rxBufferIndex = 0;
	TWI_rxBufferLength = 0;
	
	TWI_txBufferIndex = 0;
	TWI_txBufferLength = 0;
	
	twi_init();
}


uint8_t TWI_requestFrom(uint8_t address, uint8_t quantity)
{
	// clamp to buffer length
	if(quantity > TWI_BUFFER_LENGTH){
		quantity = TWI_BUFFER_LENGTH;
	}
	// perform blocking read into buffer
	uint8_t read = twi_readFrom(address, TWI_rxBuffer, quantity);
	// set rx buffer iterator vars
	TWI_rxBufferIndex = 0;
	TWI_rxBufferLength = read;
	
	return read;
}


void TWI_beginTransmission(uint8_t address)
{
	// indicate that we are transmitting
	TWI_transmitting = 1;
	// set address of targeted slave
	TWI_txAddress = address;
	// reset tx buffer iterator vars
	TWI_txBufferIndex = 0;
	TWI_txBufferLength = 0;
}


uint8_t TWI_endTransmission(void)
{
	// transmit buffer (blocking)
	int8_t ret = twi_writeTo(TWI_txAddress, TWI_txBuffer, TWI_txBufferLength, 1);
	// reset tx buffer iterator vars
	TWI_txBufferIndex = 0;
	TWI_txBufferLength = 0;
	// indicate that we are done transmitting
	TWI_transmitting = 0;
	return ret;
}

// must be called in:
// slave tx event callback
// or after beginTransmission(address)
void TWI_send(uint8_t* data, uint8_t quantity)
{
	if(TWI_transmitting){
		// in master transmitter mode
		// don't bother if buffer is full
		if(TWI_txBufferLength >= TWI_BUFFER_LENGTH){
			return;
		}
		// put byte in tx buffer
		TWI_txBuffer[TWI_txBufferIndex] = *data;
		++TWI_txBufferIndex;
		// update amount in buffer   
		TWI_txBufferLength = TWI_txBufferIndex;
	}else{
		// in slave send mode
		// reply to master
		//twi_transmit(&data, 1);
		twi_transmit(data, 1);
	}
}



// must be called in:
// slave rx event callback
// or after requestFrom(address, numBytes)
uint8_t TWI_available(void)
{
	return TWI_rxBufferLength - TWI_rxBufferIndex;
}

// must be called in:
// slave rx event callback
// or after requestFrom(address, numBytes)
uint8_t TWI_receive(void)
{
	// default to returning null char
	// for people using with char strings
	uint8_t value = '\0';
	
	// get each successive byte on each call
	if(TWI_rxBufferIndex < TWI_rxBufferLength){
		value = TWI_rxBuffer[TWI_rxBufferIndex];
		++TWI_rxBufferIndex;
	}
	
	return value;
}

// behind the scenes function that is called when data is received
void TWI_onReceiveService(uint8_t* inBytes, int numBytes)
{
	// don't bother if user hasn't registered a callback
	if(!TWI_user_onReceive){
		return;
	}
	// don't bother if rx buffer is in use by a master requestFrom() op
	// i know this drops data, but it allows for slight stupidity
	// meaning, they may not have read all the master requestFrom() data yet
	if(TWI_rxBufferIndex < TWI_rxBufferLength){
		return;
	}
	// copy twi rx buffer into local read buffer
	// this enables new reads to happen in parallel
	for(uint8_t i = 0; i < numBytes; ++i){
		TWI_rxBuffer[i] = inBytes[i];    
	}
	// set rx iterator vars
	TWI_rxBufferIndex = 0;
	TWI_rxBufferLength = numBytes;
	// alert user program
	TWI_user_onReceive(numBytes);
}

// behind the scenes function that is called when data is requested
void TWI_onRequestService(void)
{
	// don't bother if user hasn't registered a callback
	if(!TWI_user_onRequest){
		return;
	}
	// reset tx buffer iterator vars
	// !!! this will kill any pending pre-master sendTo() activity
	TWI_txBufferIndex = 0;
	TWI_txBufferLength = 0;
	// alert user program
	TWI_user_onRequest();
}

// sets function called on slave write
void TWIonReceive( void (*function)(int) )
{
	TWI_user_onReceive = function;
}

// sets function called on slave read
void TWI_onRequest( void (*function)(void) )
{
	TWI_user_onRequest = function;
}








